package momo.multitree.simulation;

import momo.multitree.algo.AllTreeVisitor;
import momo.multitree.algo.CostLastTree;
import momo.multitree.structure.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class DijkstraValidator implements AllTreeVisitor
{
	private Log log = LogFactory.getLog(DijkstraValidator.class);
	
	private final static double ACCURANCY = 1e-6;
	
	private Tree bestLatTree, bestCostTree, bestStabTree;
	private double bestLat, bestCost, bestStab;
	
	private CostLastTree costOptimizer;
	
	private boolean isOptCost = true;
	private double actualBestCost;
	
	public DijkstraValidator(Tree bestLatTree, Tree bestCostTree, Tree bestStabTree, CostLastTree costOptimizer)
	{
		this.bestLatTree = bestLatTree;
		this.bestCostTree = bestCostTree;
		this.bestStabTree = bestStabTree;
		this.costOptimizer = costOptimizer;
		
		bestLat = bestLatTree.compWeightedLatency();
		bestCost = bestCostTree.compCost(false);
		bestStab = bestStabTree.compStability();
	}

	public void visit(Tree t)
	{
		double lat = t.compWeightedLatency();
		double cost = t.compCost(false);
		double stab = t.compStability();
		
//		System.out.println("\n\n");
//		System.out.println(bestLatTree.toString());
//		System.out.println(t.toString());
		
		boolean ok = isMax(lat, cost, stab);
//		if (!ok) {
//			log.error("not ok!");
//			log.error("cost tree: "+this.bestCostTree);
//			log.error("mst tree:"+costOptimizer.getMstTree());
//			log.error("spt tree:"+costOptimizer.getSptTree());
//			log.error("tree that is better: "+t);
//		}
		
	}
	
	public boolean isMax(double lat, double cost, double stab)
	{
		boolean latSmaller = lat >= (bestLat - ACCURANCY);
		boolean costSmaller = cost >= (bestCost - ACCURANCY);
		boolean stabSmaller = stab >= (bestStab - ACCURANCY);
		
		if (!latSmaller)
			log.error("latency broken! bestlat:, " + bestLat +", lat: " + lat);
		if (!costSmaller)
		{
//			log.error("cost broken! bestCost:, " + bestCost +", cost: " + cost);
			isOptCost = false;
			actualBestCost = cost;
		}
		
		if (!stabSmaller)
			log.error("stability broken! bestStab:, " + bestStab +", stab: " + stab); 
		
		return latSmaller && stabSmaller && costSmaller;
	}
	
	public String toString()
	{
		if ( isOptCost )
			return "0, 0, 0";
		else
			return "1, " + actualBestCost + ", " + bestCost;
	}
}
